package main

import (
	"io"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"
)

func Info(format string, args ...interface{}) {
	if logLevel == "fatal" {
		return
	}
	log.Printf(format, args...)
}

func Fatal(format string, args ...interface{}) {
	log.Fatalf(format, args...)
}

func startProxyServer() {
	// 创建代理服务器
	server := &http.Server{
		Addr:    proxyServer,
		Handler: http.HandlerFunc(proxyHandler),
		// 优化连接参数
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	log.Printf("代理服务器启动，监听端口: %s", proxyServer)
	if err := server.ListenAndServe(); err != nil {
		Fatal("服务器启动失败: %v", err)
	}
}

// 代理请求处理函数
func proxyHandler(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			Info("panic: %s %s %s, err:%+v", r.Method, r.URL, r.Proto, err)
		}
	}()
	Info("收到请求: %s %s %s", r.Method, r.URL, r.Proto)

	// 处理HTTPS CONNECT请求
	if r.Method == http.MethodConnect {
		handleHTTPS(w, r)
		return
	}

	// 处理普通HTTP请求
	handleHTTP(w, r)
}

// 处理普通HTTP请求
func handleHTTP(w http.ResponseWriter, r *http.Request) {
	// 解析目标URL（从请求的URL中获取）
	if r.URL.Scheme == "" {
		r.URL.Scheme = "http" // 默认使用HTTP
	}
	if r.URL.Host == "" {
		r.URL.Host = r.Host // 使用请求头中的Host字段
	}

	// 创建反向代理
	proxy := &httputil.ReverseProxy{
		Director: func(req *http.Request) {
			// 复制原始请求
			*req = *r

			// 设置请求头
			req.Header.Set("X-Forwarded-For", getClientIP(r))
			req.Header.Set("X-Forwarded-Host", r.Host)
			req.Header.Set("X-Forwarded-Proto", r.URL.Scheme)

			// 移除代理不应该传递的头
			req.Header.Del("Proxy-Connection")
			req.Header.Del("Connection")
			req.Header.Del("Keep-Alive")
			req.Header.Del("Transfer-Encoding")
			req.Header.Del("TE")
			req.Header.Del("Upgrade")

			// 可选：添加自定义请求头
			req.Header.Set("X-Proxy-By", "Go-HTTP-Proxy")
		},
		Transport: &http.Transport{
			// 配置传输参数
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).DialContext,
			ForceAttemptHTTP2:     true,
			MaxIdleConns:          100,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
		},
		ModifyResponse: func(resp *http.Response) error {
			// 可选：修改响应头
			resp.Header.Set("X-Proxy-Processed", "true")
			return nil
		},
		ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
			Info("代理请求失败: %v", err)
			http.Error(w, "代理服务暂时不可用", http.StatusBadGateway)
		},
	}

	// 执行代理请求
	proxy.ServeHTTP(w, r)
}

// 处理HTTPS CONNECT请求（建立隧道）
func handleHTTPS(w http.ResponseWriter, r *http.Request) {
	// 解析目标主机和端口
	destHost := r.Host

	// 连接目标服务器
	destConn, err := net.DialTimeout("tcp", destHost, 10*time.Second)
	if err != nil {
		http.Error(w, "连接目标服务器失败", http.StatusServiceUnavailable)
		return
	}

	// 告诉客户端连接已建立（HTTP 200 OK）
	w.WriteHeader(http.StatusOK)

	// 获取客户端连接
	hijacker, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "不支持Hijacking", http.StatusInternalServerError)
		destConn.Close()
		return
	}

	clientConn, _, err := hijacker.Hijack()
	if err != nil {
		http.Error(w, "获取客户端连接失败", http.StatusInternalServerError)
		destConn.Close()
		return
	}

	// 双向数据转发
	go transfer(destConn, clientConn)
	go transfer(clientConn, destConn)
}

// 数据传输函数
func transfer(destination io.WriteCloser, source io.ReadCloser) {
	defer destination.Close()
	defer source.Close()
	io.Copy(destination, source)
}

// 获取客户端真实IP
func getClientIP(r *http.Request) string {
	// 尝试从XFF头获取
	if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
		// XFF格式: client, proxy1, proxy2
		if idx := strings.Index(xff, ","); idx != -1 {
			return strings.TrimSpace(xff[:idx])
		}
		return strings.TrimSpace(xff)
	}

	// 从RemoteAddr获取（格式: IP:端口）
	if ip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
		return ip
	}

	return r.RemoteAddr
}
